if(!QS) {
    var QS = {};
}

QS.Push=function(dataHandler,callback){
    var ConnectObj;
    var self=this;
	this.pullObj=null;
    this.dataHandler=dataHandler;
    this.callback=callback||{};
	
	this.getDataHandler=function(){
		return this.dataHandler;
	};
	
    this.initConnection=function(host, usr){
        if (usr) {
            ConnectObj = jslib.connectEntitlement(connectHandler, "connectEntitlement", host, usr, "256", "1.1.1.1/net", updateHandler);
        }else{
            ConnectObj = jslib.connect(connectHandler, "connectClosure", host, updateHandler);
        }
        ConnectObj.addFields(operationHandler, "addFieldsClosure", "ClosePrice", "LastPrice", "AskPrice", "BidPrice", "AskSize", "BidSize", 
            "Time","TradeTime","Date","TradeDate", "Volume","LastVolume", "HighPrice", "LowPrice", "OpenPrice","AfterTPrice","AfterTTime","AfterTDate",
            "401", "402", "404", "405", "407", "409", "-102","LastMarket","OpenInt","VWAP","MiddlePrice","MarketCentre",
            "BidOrder_0","BidOrder_1","BidOrder_2","BidOrder_3","BidOrder_4","BidOrder_5","BidOrder_6","BidOrder_7","BidOrder_8","BidOrder_9",
            "BidOrder_10","BidOrder_11","BidOrder_12","BidOrder_13","BidOrder_14","BidOrder_15","BidOrder_16","BidOrder_17","BidOrder_18","BidOrder_19",
            "BidSize_0","BidSize_1","BidSize_2","BidSize_3","BidSize_4","BidSize_5","BidSize_6","BidSize_7","BidSize_8","BidSize_9",
            "BidSize_10","BidSize_11","BidSize_12","BidSize_13","BidSize_14","BidSize_15","BidSize_16","BidSize_17","BidSize_18","BidSize_19",
            "BidPrice_0","BidPrice_1","BidPrice_2","BidPrice_3","BidPrice_4","BidPrice_5","BidPrice_6","BidPrice_7","BidPrice_8","BidPrice_9",
            "BidPrice_10","BidPrice_11","BidPrice_12","BidPrice_13","BidPrice_14","BidPrice_15","BidPrice_16","BidPrice_17","BidPrice_18","BidPrice_19",
            "AskPrice_0","AskPrice_1","AskPrice_2","AskPrice_3","AskPrice_4","AskPrice_5","AskPrice_6","AskPrice_7","AskPrice_8","AskPrice_9",
            "AskPrice_10","AskPrice_11","AskPrice_12","AskPrice_13","AskPrice_14","AskPrice_15","AskPrice_16","AskPrice_17","AskPrice_18","AskPrice_19",
            "AskSize_0","AskSize_1","AskSize_2","AskSize_3","AskSize_4","AskSize_5","AskSize_6","AskSize_7","AskSize_8","AskSize_9",
            "AskSize_10","AskSize_11","AskSize_12","AskSize_13","AskSize_14","AskSize_15","AskSize_16","AskSize_17","AskSize_18","AskSize_19",
            "AskOrder_0","AskOrder_1","AskOrder_2","AskOrder_3","AskOrder_4","AskOrder_5","AskOrder_6","AskOrder_7","AskOrder_8","AskOrder_9",
            "AskOrder_10","AskOrder_11","AskOrder_12","AskOrder_13","AskOrder_14","AskOrder_15","AskOrder_16","AskOrder_17","AskOrder_18","AskOrder_19",
            "1900","1901","1902","1903","1904","256","257","258","259","260","261","262","263","264","265","266","267","268","269","270","271","272","273",
            "274","275","276","277","278","279","280","281","282","283","284","285","286","287","288","289","290","291","292","293","294","295","296","297",
            "298","299","300","301","302","303","304","305","306","307","308","309","310","311","312","313","314","315","316","317","318","319","320","321",
            "322","323","324","325","326","327","328","329","330","331","332","333","334","335","336","337","338","349","340","341","342","343","344","345",
            "346","347","348","349","1904", "909","910","911","912","913","914"     
        );
//        isConnected = true;
    };
    
	this.disconnect=function(){
		if(ConnectObj){
			ConnectObj.disconnect(function(closure, eventType, event, body){
			},"connectClosure");
		}
	};
    
	this._subscribeConsolidatedTickers = function(channels,pushSubSeparator){
		//sent consolidated ticker list to DSS
		var sbstr = "ConnectObj.subscribe(operationHandler, \"subscribeClosure\"";
		sbstr += ", \"" + channels[0].sourceType + "\", \"-1." + Math.random() + "\"";
		tks = "";
		var count = 0;
		for (var j = 0; j < channels.length; j++) {
			chn = channels[j];
			if(count > 80){ //only send the first 80 tickers
				break;
			}
			if(parseInt(chn.serviceName) >= 126){ //filter out the sub-exch
				tk = chn.itemName.split(pushSubSeparator);
				if(tk[2] == "-1" || tk[2] == "0"){ //only send subcode == -1/0
					tks += chn.serviceName + "." + tk[0] + "." + tk[1] + ",";
					count++;
				}
			}
		}
		sbstr += ", \"" + tks + "\")";
		eval(sbstr);
	};
	
	this._subscribeToPull = function(channels,pushSubSeparator){
		if(this.pullObj==null){
			this.pullObj=new QS.Pull(this.dataHandler);
			this.pullObj.setPullService(QSAPI.getQSPullPath()+"getPullQuote.jsp");
		}
		var pullTickers = [];
		for (var j = 0; j < channels.length; j++) {
			chn = channels[j];
			tk = chn.itemName.split(pushSubSeparator);
			if(tk[2] == "-1" || tk[2] == "0"){ //only send subcode == -1/0
				pullTickers.push(chn.serviceName + "." + tk[0] + "." + tk[1]);
			}
		}
		this.pullObj.batchSubscribe(pullTickers);
	};
	
	
    this.batchSubscribe = function(channels){
	
		if(channels.length>50){
			var subSeparator=this.dataHandler.getSubSeparator();
			//sent consolidated ticker list to DSS
			this._subscribeConsolidatedTickers(channels,subSeparator['push']);
			//get init data by Pull for faster loading
			this._subscribeToPull(channels,subSeparator['push']);
		}
		
        var str = "ConnectObj.subscribe(operationHandler, \"subscribeClosure\"";
		var count=0;
        for (var j = 0; j < channels.length; j++) {
            chn = channels[j];
            str += ", \"" + chn.sourceType + "\", \"" + chn.serviceName + "\", \"" + chn.itemName + "\""; // jacye
            if ((j + 1) % 50 == 0 || j == channels.length - 1) {
				str += ")";
				count++;
				with({str:str, count:count}){
					setTimeout(function(){
						eval(str);
					}, 300*count);
				}
                str = "ConnectObj.subscribe(operationHandler, \"subscribeClosure\"";
            }
        }
		
		
    };
    
    //
    this.batchUnsubscribe = function(channels,notDeleteInfoFromGData){
        var str = "ConnectObj.unsubscribe(operationHandler, \"unsubscribeClosure\"";
        for (var j = 0; j < channels.length; j++) {
            chn = channels[j];
            str += ", \"" + chn.sourceType + "\", \"" + chn.serviceName + "\", \"" + chn.itemName + "\""; // jacye
            if ((j + 1) % 50 == 0 || j == channels.length - 1) {
                str += ")";
                eval(str);
                str = "ConnectObj.unsubscribe(operationHandler, \"unsubscribeClosure\"";
            }
        }
        
    };
	
    
	function connectHandler(closure, eventType, event, body){
		if (eventType == jslib.OPERATION_ERROR) {
            var err;
            switch (event) {
                case jslib.ERROR_CONNECTED:
                    err = "You are already connected";
                    break;
                case jslib.ERROR_NOT_CONNECTED:
                    err = "You are not connected";
                    break;
                case jslib.ERROR_TIMEOUT:
                    err = "Connection timeout";
                    break;
                case jslib.ERROR_HTTP:
                    err = "HTTP status error. The HTTP status is: " + body;
                    break;
                case jslib.ERROR_SERVER:
                    err = "Server side error: " + body;
                    break;
                case jslib.ERROR_DOMAIN:
                    err = "Domain error.";
                    break;
                case jslib.ERROR_SERVER_DOWN:
                    err = "Server down.";
                    break;
            }
            if(typeof self.callback.onFailure=='function'){
                self.callback.onFailure({
					errorCode:'-1',
					errorMessage:'Connect push server unsuccessfully.'
				});
            }
            //alert("Error: " + closure + ", " + err);
        } else if (eventType == jslib.OPERATION_OK) {
            // everything is ok
            if(typeof self.callback.onSuccess=='function'){
                self.callback.onSuccess({
					errorCode:'0',
					errorMessage:'Connect push server successfully.'
				});
            }
        }
	};
	
    function operationHandler(closure, eventType, event, body) {		
        if (eventType == jslib.OPERATION_ERROR) {
            var err;
            switch (event) {
                case jslib.ERROR_CONNECTED:
                    err = "You are already connected";
                    break;
                case jslib.ERROR_NOT_CONNECTED:
                    err = "You are not connected";
                    break;
                case jslib.ERROR_TIMEOUT:
                    err = "Connection timeout";
                    break;
                case jslib.ERROR_HTTP:
                    err = "HTTP status error. The HTTP status is: " + body;
                    break;
                case jslib.ERROR_SERVER:
                    err = "Server side error: " + body;
                    break;
                case jslib.ERROR_DOMAIN:
                    err = "Domain error.";
                    break;
                case jslib.ERROR_SERVER_DOWN:
                    err = "Server down.";
                    break;
            }
            //alert("Error: " + closure + ", " + err);
        } else if (eventType == jslib.OPERATION_OK) {
            // everything is ok
        }
    }
    
    function updateHandler(closure, eventType, event, body) {
        if (eventType == jslib.STREAMING_ERROR) {
            alert("Streaming error=" + event + ", body=" + body);
        } else if (eventType == jslib.MESSAGE_RECEIVED) {
            switch (event) {
                case jslib.MARKET_PRICE_UPDATE:
                    updateMarketPrice(body);
                    break;
                case jslib.STATUS_UPDATE:
                    updateStatus(body);
                    break;
            }
        }
    }
    
    
    function updateMarketPrice(body){
        self.dataHandler.updateMarketPrice(body,gData);
    }
    
    function updateStatus(body) {
        var msg = "";
        var sourceType = body.source;
        var serviceName = body.service;
        var itemName = body.symbol;
        var itemState = body.state;
        var itemStatus = body.status;
        msg += sourceType+"|"+serviceName+"|"+itemName + " is " + itemState + "|"+itemStatus+"\n";
        if (!this.pause) {
            this.pause = true;
            setTimeout(function(){self.dataHandler.pause = false; alert(msg); msg = "";  }, 30000);
        }
    }
    
};